//---------------------------------------------------------------------------------
// Copyright (c) 2008 Metaphor Game Engine Project
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//     1. The origin of this software must not be misrepresented; you must not
//        claim that you wrote the original software. If you use this software
//        in a product, an acknowledgment in the product documentation would be
//        appreciated but is not required.
//
//     2. Altered source versions must be plainly marked as such, and must not be
//        misrepresented as being the original software.
//
//     3. This notice may not be removed or altered from any source
//        distribution.
//---------------------------------------------------------------------------------

#ifndef __VLHidManager_H__
#define __VLHidManager_H__

#include <ois/OISMouse.h>
#include <ois/OISKeyboard.h>
#include <ois/OISJoyStick.h>
#include <ois/OISInputManager.h>

class wxWindow;

// Adapted from http://www.ogre3d.org/wiki/index.php/Using_OIS
// Almost certainly LGPL licensed as ogre is LGPL


//! Wraps OIS to allow arbitrary listeners and simple initialisation and maintenance.

/// While the ctor does take an Ogre::RenderWindow to init, the library itself 
/// does not depend on Ogre. Extend this class and create a new initialize 
/// function to support an arbitrary system.
///
/// Input can be polled calling getKeyboard(), getMouse(), and getJoystick(). Also, a
/// class can register for input by using OIS::KeyListener, OIS::MouseListener, or 
/// OIS::JoyStickListener
class VLHidManager : public OIS::KeyListener, 
                     public OIS::MouseListener, 
                     public OIS::JoyStickListener
{

public:
  //! Create exactly one of these classes anywhere and however you want, then use HidManager::getSingleton().
  VLHidManager( void );
  virtual ~VLHidManager( void );

  //! Pass the current RenderWindow to get input for.
  void initialize( wxWindow *window );

  //! Call once every frame.
  void capture( void );

  //! Register a new key listener
  void addKeyListener( OIS::KeyListener *keyListener, const std::string& instanceName );

  //! Register a new mouse listener
  void addMouseListener( OIS::MouseListener *mouseListener, const std::string& instanceName );

  //! Register a new joystick listener
  void addJoystickListener( OIS::JoyStickListener *joystickListener, const std::string& instanceName );

  //! Unregister a key listener
  void removeKeyListener( const std::string& instanceName );

  //! Unregister a mouse listener
  void removeMouseListener( const std::string& instanceName );

  //! Unregister a joystick listener
  void removeJoystickListener( const std::string& instanceName );

  //! Unregister a key listener
  void removeKeyListener( OIS::KeyListener *keyListener );

  //! Unregister a mouse listener
  void removeMouseListener( OIS::MouseListener *mouseListener );

  //! Unregister a joystick listener
  void removeJoystickListener( OIS::JoyStickListener *joystickListener );

  //! Unregister all listeners
  void removeAllListeners( void );

  //! Unregister all key listeners
  void removeAllKeyListeners( void );

  //! Unregister all mouse listeners
  void removeAllMouseListeners( void );

  //! Unregister all joystick listeners
  void removeAllJoystickListeners( void );

  //! Call every time the window is resized.
  void setWindowExtents( int width, int height );

  //! Get mouse state object
  OIS::Mouse*    getMouse( void );

  //! Get keyboard state object
  OIS::Keyboard* getKeyboard( void );

  //! Get joystick state object
  OIS::JoyStick* getJoystick( unsigned int index );

  //! Get number of joysticks being listened to
  int getNumOfJoysticks( void );
private:
  VLHidManager( const VLHidManager& ) { }
  VLHidManager & operator = ( const VLHidManager& );

  bool keyPressed( const OIS::KeyEvent &e );
  bool keyReleased( const OIS::KeyEvent &e );

  bool mouseMoved( const OIS::MouseEvent &e );
  bool mousePressed( const OIS::MouseEvent &e, OIS::MouseButtonID id );
  bool mouseReleased( const OIS::MouseEvent &e, OIS::MouseButtonID id );

  bool povMoved( const OIS::JoyStickEvent &e, int pov );
  bool axisMoved( const OIS::JoyStickEvent &e, int axis );
  bool sliderMoved( const OIS::JoyStickEvent &e, int sliderID );
  bool buttonPressed( const OIS::JoyStickEvent &e, int button );
  bool buttonReleased( const OIS::JoyStickEvent &e, int button );

  OIS::Mouse        *mMouse;
  OIS::Keyboard     *mKeyboard;
  OIS::InputManager *mInputSystem;

  std::vector<OIS::JoyStick*> mJoysticks;
  std::vector<OIS::JoyStick*>::iterator itJoystick;
  std::vector<OIS::JoyStick*>::iterator itJoystickEnd;

  std::map<std::string, OIS::KeyListener*> mKeyListeners;
  std::map<std::string, OIS::MouseListener*> mMouseListeners;
  std::map<std::string, OIS::JoyStickListener*> mJoystickListeners;

  std::map<std::string, OIS::KeyListener*>::iterator itKeyListener;
  std::map<std::string, OIS::MouseListener*>::iterator itMouseListener;
  std::map<std::string, OIS::JoyStickListener*>::iterator itJoystickListener;

  std::map<std::string, OIS::KeyListener*>::iterator itKeyListenerEnd;
  std::map<std::string, OIS::MouseListener*>::iterator itMouseListenerEnd;
  std::map<std::string, OIS::JoyStickListener*>::iterator itJoystickListenerEnd;
};

#endif